#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
const int N=1e5+5;
const double eps=1e-6;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
int wtp,wstk[40];
void write(int x,char c){
    if(x<0) x=-x,putchar('-');
    do{wstk[++wtp]=x%10,x/=10;}while(x);
    while(wtp){putchar(wstk[wtp--]^48);}
    if(c) putchar(c);
}
int n,m,ans,LEN,tot,det[N],L[N],R[N];double V;
struct node{int st;double v,a;}car[N];
struct segment{int l,r;}seg[N];
bool cmp(segment a,segment b){return a.r<b.r;}
int tr[N<<2];
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r>>1)
void build(int p,int l,int r){
    tr[p]=0;if(l==r) return;
    build(ls,l,mid),build(rs,mid+1,r);
}
void update(int p,int l,int r,int x){
    if(l==r) return tr[p]=1,void();
    if(x<=mid) update(ls,l,mid,x);else update(rs,mid+1,r,x);
    tr[p]=tr[ls]+tr[rs];
}
int query(int p,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr) return tr[p];
    if(qr<=mid) return query(ls,l,mid,ql,qr);
    else if(ql>mid) return query(rs,mid+1,r,ql,qr);
    else return query(ls,l,mid,ql,qr)+query(rs,mid+1,r,ql,qr);
}
#undef ls
#undef rs
#undef mid
void solve(){
    n=read(),m=ans=read(),LEN=read(),scanf("%Lf",&V);
    for(int i=1;i<=n;i++) car[i].st=read(),scanf("%Lf%Lf",&car[i].v,&car[i].a);
    for(int i=1;i<=m;i++) det[i]=read();
    for(int i=1,p;i<=n;i++){
        L[i]=R[i]=0;
        if(car[i].a==0){
            if(car[i].v-V>eps){
                L[i]=lower_bound(det+1,det+m+1,car[i].st)-det,R[i]=m;
                if(L[i]>R[i]) L[i]=R[i]=0;
            }
        }
        else if(car[i].a<0){
            if(car[i].v-V>eps){
                L[i]=lower_bound(det+1,det+m+1,car[i].st)-det;
                double tmp=car[i].st+(V*V-car[i].v*car[i].v)/(2.0*car[i].a);
                R[i]=lower_bound(det+1,det+m+1,(int)ceil(tmp))-det-1;
                if(L[i]>R[i]) L[i]=R[i]=0;
            }
        }
        else{
            if(car[i].v-V>eps){
                L[i]=lower_bound(det+1,det+m+1,car[i].st)-det,R[i]=m;
                if(L[i]>R[i]) L[i]=R[i]=0;
            }
            else{
                double tmp=car[i].st+(V*V-car[i].v*car[i].v)/(2.0*car[i].a);
                L[i]=lower_bound(det+1,det+m+1,(int)floor(tmp+1))-det,R[i]=m;
                if(L[i]>R[i]) L[i]=R[i]=0;
            }
        }
    }
    tot=0;
    for(int i=1;i<=n;i++) if(1<=L[i]&&L[i]<=R[i]&&R[i]<=m) seg[++tot]={L[i],R[i]};
    sort(seg+1,seg+tot+1,cmp);
    build(1,1,m);
    for(int i=1;i<=tot;i++) if(query(1,1,m,seg[i].l,seg[i].r)==0) update(1,1,m,seg[i].r),ans--;
    write(tot,' '),write(ans,'\n');
}
signed main(){
    freopen("detect.in","r",stdin);
    freopen("detect.out","w",stdout);
    for(int T=read();T;T--) solve();
    return 0;
}
